<?php

namespace app\admin\service;

use app\admin\model\Admin;
use app\admin\model\Menu;
use common\enum\ResultCode;
use Tinywan\ExceptionHandler\Exception\BadRequestHttpException;
use Tinywan\ExceptionHandler\Exception\NotFoundHttpException;
use Webman\Event\Event;

class AdminService extends BaseCurdService
{
    /**
     * 获取管理员列表
     * @param array $params 查询参数
     * @return array
     */
    public function getList(array $params): array
    {
        $query = Admin::query();
        return $this->paginateQuery($query, $params, ['user_name', 'mobile', 'email'], ['status']);
    }


    /**
     * 获取管理员信息
     * @param int $id 管理员ID
     * @return Admin|null
     */
    public function getInfo(int $id): ?Admin
    {
        $query = Admin::query();
        $query->with([
            'roles' => function ($query) {
                $query->with([
                    'menus' => function ($query) {
                        $query->where('status', 1)->orderBy('sort', 'asc');
                    },
                ]);
            },
        ]);
        $admin = $query->find($id);
        if (!$admin) {
            throw new NotFoundHttpException(ResultCode::DATA_NOT_FOUND->getDescription());
        }
        if ($id === 1) {
            $admin->flat_menus = Menu::where('status', 1)->orderBy('sort', 'asc')->get()->toArray();
        } else {
            $menus = collect();
            foreach ($admin->roles as $role) {
                $menus = $menus->merge($role->menus);
            }
            $admin->flat_menus = $menus->unique('id')->values()->toArray();
        }
        return $admin;
    }

    /**
     * 创建管理员
     * @param array $data 管理员数据
     * @return Admin
     */
    public function create(array $data): Admin
    {
        // 检查管理员账号是否已存在
        if (Admin::where('user_name', $data['user_name'])->exists()) {
            throw new BadRequestHttpException('管理员账号已存在');
        }
        // 检查手机号是否已存在
        if (!empty($data['mobile']) && Admin::where('mobile', $data['mobile'])->exists()) {
            throw new BadRequestHttpException('手机号已存在');
        }
        // 密码加密
        if (!empty($data['password'])) {
            $data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
        }
        return Admin::create($data);
    }

    /**
     * 更新管理员
     * @param int $id 管理员ID
     * @param array $data 更新数据
     * @return bool
     */
    public function update(int $id, array $data): bool
    {
        $admin = Admin::find($id);
        if (!$admin) {
            throw new NotFoundHttpException(ResultCode::DATA_NOT_FOUND->getDescription());
        }
        // 检查管理员账号是否已存在
        if (isset($data['user_name']) && Admin::where('user_name', $data['user_name'])->where('id', '!=', $id)->exists()) {
            throw new BadRequestHttpException('管理员账号已存在');
        }
        // 检查手机号是否已存在
        if (!empty($data['mobile']) && Admin::where('mobile', $data['mobile'])->where('id', '!=', $id)->exists()) {
            throw new BadRequestHttpException('手机号已存在');
        }
        // 密码加密
        if (array_key_exists('password', $data)) {
            if (!empty($data['password'])) {
                $data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
            } else {
                unset($data['password']);
            }
        }
        $result = $admin->update($data);
        if ($result) {
            Event::emit('admin.status.changed', ['adminId' => $id, 'status' => $data['status']]);
        }
        return $result;
    }

    /**
     * 删除管理员
     * @param int $id 管理员ID
     * @return bool|null
     */
    public function delete(int $id): ?bool
    {
        $admin = Admin::find($id);
        if (!$admin) {
            throw new NotFoundHttpException(ResultCode::DATA_NOT_FOUND->getDescription());
        }
        if ($admin->id === 1) {
            throw new BadRequestHttpException('超级管理员禁止删除');
        }
        $result = $admin->delete();
        if ($result) {
            Event::emit('admin.deleted', ['adminId' => $id]);
        }
        return $result;
    }

    /**
     * 管理员授权角色
     * @param int $adminId 管理员ID
     * @param array $roleIds 角色ID列表
     * @return array|array[]
     */
    public function grantRoles(int $adminId, array $roleIds): array
    {
        $admin = Admin::find($adminId);
        if (!$admin) {
            throw new NotFoundHttpException(ResultCode::DATA_NOT_FOUND->getDescription());
        }
        $result = $admin->roles()->sync($roleIds);
        Event::emit('admin.roles.granted', ['adminId' => $adminId]);
        return $result;
    }
}